package hstring

import (
	"crypto/md5"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"os"
	"strconv"
	"sync/atomic"
	"time"

	"github.com/bwmarrin/snowflake"
	"github.com/gogf/gf/v2/crypto/gmd5"
	"github.com/gogf/gf/v2/os/gtime"
	"github.com/gogf/guuid"
)

// 获取 UUID
func UUID() (uuid string) {

	u := guuid.New()
	uuid = fmt.Sprint(u)

	return
}

// 更好的随机值
func EnUniqid(unique ...string) (res string) {
	if len(unique) == 0 {
		uuid := UUID()
		res, _ = gmd5.Encrypt(uuid)
	} else {
		res, _ = gmd5.Encrypt(unique[0] + gtime.Date())
	}

	return
}

// Sha256 加密
func Sha256(src string) (res string) {
	m := sha256.New()
	m.Write([]byte(src))
	res = hex.EncodeToString(m.Sum(nil))
	return
}

// MD5 加密 (32位)
func MD5(src string) (res string) {
	b := md5.Sum([]byte(src))
	s := fmt.Sprintf("%x", b)
	res = string(s)

	return
}

// MD5 加密 (16位)
func MD5To16(src string) string {
	return MD5(src)[8:24]
}

// 生成24位订单号
// 前面17位代表时间精确到毫秒，中间3位代表进程id，最后4位代表序号
// 生成订单号
// 生成位数,19位日期模板:20060102(年月日), 24位日期模板:20060102150405(年月日时分秒)
var increment int64 // 增量

func BuilderOrderSn() string {

	var (
		t = time.Now()
	)

	s := time.Now().Format("20060102150405")
	m := t.UnixNano()/1e6 - t.UnixNano()/1e9*1e3
	ms := sup(m, 3)
	p := os.Getpid() % 1000
	ps := sup(int64(p), 3)
	i := atomic.AddInt64(&increment, 1)
	r := i % 10000
	rs := sup(r, 4)
	n := fmt.Sprintf("%s%s%s%s", s, ms, ps, rs)
	return n
}

// 雪花算法 唯一ID
func SnowflakeID() int64 {

	node, err := snowflake.NewNode(1)
	if err != nil {
		fmt.Println(err)
		return 0
	}

	id := node.Generate().Int64()

	return id
}

// 对长度不足n的数字前面补0
func sup(i int64, n int) string {
	m := fmt.Sprintf("%d", i)
	for len(m) < n {
		m = fmt.Sprintf("0%s", m)
	}
	return m
}

// 把二进制切片转十六进制切片
func BinaryToHexadecimal(binarySlice []string) []string {

	for k, v := range binarySlice {
		decimalVal, _ := strconv.ParseInt(v, 2, 64)
		hexString := strconv.FormatInt(decimalVal, 16)
		binarySlice[k] = hexString
	}

	return binarySlice
}

// 把字符串按指定数量切割
func StrSplitNumber(str string, number int) []string {
	result := []string{}

	numChars := number
	for i := 0; i < len(str); i += numChars {
		end := i + numChars
		if end > len(str) {
			end = len(str)
		}

		result = append(result, str[i:end])
	}

	return result
}

// 替换字符串
// 源字符串,要替换的字符串,替换的位置
func ReplaceString(source, chars string, place int) string {

	var (
		lenth = len(chars)    // 替换的长度
		start = place - lenth // 起始位置
		end   = place         // 结束位置
	)

	result := source[:start] + chars + source[start+lenth:end] + source[end:]

	return result
}
